package com.Spring.test_2_3_spring_principle.controller;

import com.Spring.test_2_3_spring_principle.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;

@RequestMapping("/scope")
public class BeanScopeController {
    @Autowired
    private ApplicationContext context;
    @Resource(name = "singleUser")  // 指明注入哪一个
    private User singleUser;

    @Resource(name = "prototypeUser")
    private User prototypeUser;

    @Resource(name = "requestUser")
    private User requestUser;

    @Resource(name = "sessionUser")
    private User sessionUser;

    @Resource(name = "applicationUser")
    private User applicationUser;


    @RequestMapping("/single")
    public String single(){
        /**
         * 1. 从context获取对象
         * 2. 属性注入获取对象
         */
        User user = (User) context.getBean("singleUser"); // 根据名称去获取
        return "context获取的对象:"+user+",属性注入获取的对象:"+singleUser;

    }

    // 多例
    @RequestMapping("/prototype")
    public String prototype(){
        /**
         * 1. 从context获取对象
         * 2. 属性注入获取对象
         */
        User user = (User) context.getBean("prototypeUser"); // 从 BeanConfig 里面获取多例对象
        return "context获取的对象:"+user+",属性注入获取的对象:"+prototypeUser;

        // context获取的对象 每次刷新 获取的对象地址 是一直改变的 , 而属性注入获取的对象 一直不会改变
    }

    // request 作用域
    @RequestMapping("/request")
    public String request(){
        /**
         * 1. 从context获取对象
         * 2. 属性注入获取对象
         */
        User user = (User) context.getBean("requestUser"); // User user  这个 是 User的代理类
        System.out.println(user.toString()); // 这个 是 目标类 , Spring 代理的时候进行了重写, 逻辑是: 执行目标类的toString 方法
        System.out.println(user.getClass().getName() + "@" + Integer.toHexString(user.hashCode())); // 这个是一个代理类
        // 理论上来说 这两行的打印结果应该是一样的
        // 但是实际结果却是: 两个完全不一样
        // 原因是: 这个 user 其实是一个代理对象, Spring 底层是一个代理对象
        return "context获取的对象:"+user+",属性注入获取的对象:"+requestUser;
        // request 作用域, 每次刷新 这两个 得到的都是同一个,
        //          但是每次刷新之后这两个获取的都会改变不同的引用对象的地址 (存放再栈中的)
        //      每一次请求都会重新创建对象
        // 再同一个请求中 拿到的是同一个

        // request 请求的时候, 引用对象的地址发生了变化
        // 但是 最底层指向堆里面的还是同一个 (真正的)
    }

    // session作用域
    @RequestMapping("/session")
    public String session(){
        /**
         * 1. 从context获取对象
         * 2. 属性注入获取对象
         */
        User user = (User) context.getBean("sessionUser"); // 此处的user是相当于一个代理对象
//        return "context获取的对象:"+System.identityHashCode(user)+",属性注入获取的对象:"+System.identityHashCode(sessionUser);
        // 这个打印的是一个内存地址
        return "context获取的对象:"+user+",属性注入获取的对象:"+sessionUser; // 现在打印的是一个引用的对象

        // 在同一个会话中 获取的是同一个对象, 多次请求也是获取的同一个地址
        // 但是清除缓存之后 就会 创建一个新的会话, 这样就会获取另一个新的地址
        // 所以再最底层作用的还是同一个地址
    }


    // application 作用域
    @RequestMapping("/application")
    public String application(){
        /**
         * 1. 从context获取对象
         * 2. 属性注入获取对象
         */
        User user = (User) context.getBean("applicationUser");
//        return "context获取的对象:"+System.identityHashCode(user)+",属性注入获取的对象:"+System.identityHashCode(sessionUser);
        return "context获取的对象:"+user+",属性注入获取的对象:"+applicationUser;

        // application 再整个应用中是同一个
    }

}
